<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="TZNIv" id="TZNIv"><span data-lake-id="u6537a020" id="u6537a020">典型回答</span></h1>
  <p data-lake-id="u9d3cba7b" id="u9d3cba7b"><span data-lake-id="ue6bafcba" id="ue6bafcba">Java.util包中的List接口继承了Collection接口，用来存放对象集合，所以对这些对象进行排序的时候，要么让对象类自己实现同类对象的比较，要么借助比较器进行比较排序。</span></p>
  <p data-lake-id="u107fe922" id="u107fe922"><span data-lake-id="ub7113cf0" id="ub7113cf0">​</span><br></p>
  <p data-lake-id="ucd442788" id="ucd442788"><span data-lake-id="u3fc7b33c" id="u3fc7b33c">举例：学生实体类，包含姓名和年龄属性，比较时先按姓名升序排序，如果姓名相同则按年龄升序排序。</span></p>
  <h2 data-lake-id="v60XJ" id="v60XJ"><span data-lake-id="u82a9e401" id="u82a9e401">实现Comparable</span></h2>
  <p data-lake-id="uf72e0cd0" id="uf72e0cd0"><span data-lake-id="ub2b13c50" id="ub2b13c50">第一种：实体类自己实现Comparable接口比较</span></p>
  <pre lang="java"><code>
public class Student implements Comparable&lt;Student&gt;{ 
    private String name; 
    private int age; 
    @Override 
    public int compareTo(Student o) {
        int flag = this.name.compareTo(o.name); 
        if(flag == 0) { 
        	flag = this.age - o.age; 
        } 
        return flag; 
    } 
}
Collections.sort(students);
</code></pre>
  <h2 data-lake-id="RAEkk" id="RAEkk"><span data-lake-id="u32802e76" id="u32802e76">借助Comparator</span></h2>
  <p data-lake-id="ue54fe369" id="ue54fe369"><span data-lake-id="u90d2db53" id="u90d2db53">第二种：借助比较器进行排序。</span></p>
  <pre lang="java"><code>
public class Student { 
    private String name; 
	private int age; 
}
Collections.sort(students, (o1, o2) -&gt; {
	int flag = o1.getName().compareTo(o2.getName()); 
    if(flag == 0) { 
        flag = o1.getAge() - o2.getAge(); 
    } 
    return flag; 
}); 
</code></pre>
  <p data-lake-id="ub98846a4" id="ub98846a4"><br></p>
  <p data-lake-id="uded9eb69" id="uded9eb69"><span data-lake-id="u245514cb" id="u245514cb">也可以直接优化成：</span></p>
  <p data-lake-id="u52cdf6cd" id="u52cdf6cd"><span data-lake-id="ud90e673c" id="ud90e673c">​</span><br></p>
  <pre lang="java"><code>
Collections.sort(students, Comparator.comparing(Student::getName).thenComparingInt(Student::getAge));
</code></pre>
  <h2 data-lake-id="A5E4U" id="A5E4U"><span data-lake-id="u6abbbd21" id="u6abbbd21">通过Stream</span></h2>
  <p data-lake-id="u7f484b81" id="u7f484b81"><span data-lake-id="ucb80307c" id="ucb80307c">第三种：借助Stream进行排序，借助Stream的API，底层还是通过Comparable实现的。</span></p>
  <pre lang="java"><code>
public class Student { 
    private String name; 
	private int age; 
}
// 如果Student实现了Comparable
students.stream().sorted().collect(Collectors.toList());
// 如果Student没有实现Comparable

students.stream().sorted((o1, o2) -&gt; {
	int flag = o1.getName().compareTo(o2.getName()); 
    if(flag == 0) { 
        flag = o1.getAge() - o2.getAge(); 
    } 
    return flag; 
}).collect(Collectors.toList());
</code></pre>
  <h1 data-lake-id="jiPL0" id="jiPL0"><span data-lake-id="u1722f38a" id="u1722f38a">知识扩展</span></h1>
  <h2 data-lake-id="WgxyO" id="WgxyO"><strong><span data-lake-id="uc801e7fa" id="uc801e7fa" class="lake-fontsize-24" style="color: rgb(38, 38, 38)">有了Comparable为什么还需要Comparator？</span></strong></h2>
  <p data-lake-id="u8d18e530" id="u8d18e530"><span data-lake-id="u7c6bafd8" id="u7c6bafd8">Comparable用于使某个类具备可排序能力。如之前的Student类，实现该接口后覆盖其compareTo方法，即可具备可排序的能力。</span></p>
  <p data-lake-id="u8a42b034" id="u8a42b034"><span data-lake-id="uad3be41a" id="uad3be41a">但是仍然存在一些二方库的类没有实现Comparable，但是调用方也需要比较的，此时就需要使用Comparator接口。</span></p>
  <p data-lake-id="ucce879a5" id="ucce879a5"><span data-lake-id="ud8a221eb" id="ud8a221eb">Comparator是一个比较器接口，可以用来给不具备排序能力的对象进行排序。如上述代码中对不具备排序能力的Student进行排序</span></p>
  <h2 data-lake-id="jU1dI" id="jU1dI"><span data-lake-id="u33b766d3" id="u33b766d3">compareTo和equals的使用场景有何区别?</span></h2>
  <p data-lake-id="u05b1c145" id="u05b1c145"><span data-lake-id="u0c87502e" id="u0c87502e">compareTo常用于排序和BigDecimal等数值的比较</span></p>
  <p data-lake-id="uec2fbeb1" id="uec2fbeb1"><span data-lake-id="u3dce887c" id="u3dce887c">equals则是常用于业务语义中两个对象是否相同，如String常常通过equals来比较是否字面意义相同</span></p>
  <h2 data-lake-id="QnK4M" id="QnK4M"><span data-lake-id="u8e2202bb" id="u8e2202bb">既然Set是无序的，还怎么排序？</span></h2>
  <p data-lake-id="uc06ba2bb" id="uc06ba2bb"><span data-lake-id="ud7c0400a" id="ud7c0400a">这里说的是两个语境的不同，Set的无序，指的是插入顺序是无序的。虽然Set的插入顺序是无序的，Set也可以基于SortedSet要求对象实现Comparable来对Set中的元素进行排序。</span></p>
  <h3 data-lake-id="rNaCz" id="rNaCz"><span data-lake-id="u5a8aceb3" id="u5a8aceb3">Set真的是插入无序的吗？</span></h3>
  <p data-lake-id="ub297f901" id="ub297f901"><span data-lake-id="u10c22aaf" id="u10c22aaf">并不是，Set有一个实现类是LinkedHashSet，它引用了LinkedHashMap，通过双向链表记录了每个node的插入顺序和查询顺序（可选），以此来达到Set的插入有序性。</span></p>
 </body>
</html>